package fmu.pi.business;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import fmu.pi.model.bean.Cartao;
import fmu.pi.model.bean.Conta;
import fmu.pi.model.bean.Entidade;
import fmu.pi.model.bean.Grupo;
import fmu.pi.model.bean.Movimentacao;
import fmu.pi.model.bean.Usuario;
import fmu.pi.model.dao.MovimentacaoDao;
import fmu.pi.model.dao.old.CartaoDao;
import fmu.pi.model.dao.old.ContaDao;
import fmu.pi.model.dao.old.Dao;
import fmu.pi.model.dao.old.GrupoDao;
import fmu.pi.model.dao.old.UsuarioDao;

public class MovimentacaoBusiness_OLD {
	private Usuario usuario;
	//private List<Grupo> groupList;
	private List<Conta> accountList;
	//private List<Cartao> cardList;
	private List<Movimentacao> movListTotal;
	// lista de movimentações apartir de uma data especificada
	private List<Movimentacao> movList = new ArrayList<Movimentacao>();
	private static Float saldo = 0f; // saldo do usuário

	// construtor
	public MovimentacaoBusiness_OLD() {
		init(); // le as tabelas
	}

	private void init() {
		createUsuario();
		movListTotal = movs();
		accountList = contas();
		//cardList = cards();
		//groupList = grupos();

		geraSaldo();
	}

	private void createUsuario() {
		Dao dao = new UsuarioDao();

		for (int i = 0; i < dao.read().size(); i++)
			usuario = (Usuario) dao.read().get(i);
	}

	public List<Grupo> grupos() {
		Dao dao = new GrupoDao();
		List<Entidade> entidades = dao.read();
		List<Grupo> grupos = new ArrayList<Grupo>();

		for (int i = 0; i < entidades.size(); i++)
			grupos.add((Grupo) entidades.get(i));

		return grupos;
	}

	public List<Conta> contas() {
		Dao dao = new ContaDao();
		List<Entidade> entidades = dao.read();
		List<Conta> contas = new ArrayList<Conta>();

		for (int i = 0; i < entidades.size(); i++)
			contas.add((Conta) entidades.get(i));

		return contas;
	}

	public List<Cartao> cards() {
		Dao dao = new CartaoDao();
		List<Entidade> entidades = dao.read();
		List<Cartao> cards = new ArrayList<Cartao>();

		for (int i = 0; i < entidades.size(); i++)
			cards.add((Cartao) entidades.get(i));

		return cards;
	}

	private List<Movimentacao> movs() {
		Dao dao = new MovimentacaoDao();
		List<Entidade> entidades = dao.read();
		List<Movimentacao> movs = new ArrayList<Movimentacao>();

		for (int i = 0; i < entidades.size(); i++)
			movs.add((Movimentacao) entidades.get(i));

		return movs;
	}

	private void geraSaldo() {
		tipoTransaction();// determina se a movimentação é receber ou a pagar

		saldo = 0f;
		for (int i = 0; i < movListTotal.size(); i++) {
			// Obtém o saldo
			saldo = saldo
					+ (movListTotal.get(i).getCredito() + movListTotal.get(i)
							.getDebito());
		}
	}

	public Float geraSaldo(String dateIndex) {
		Float saldo = 0f;
		try {
			SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
			String firstDateIndex = "01/01/1900";
			Date firstDate = df.parse(firstDateIndex);
			Date lastDate = df.parse(dateIndex);

			geraExtrato(firstDate, lastDate);
			Integer ultimoIndice = 0;

			if (movList.size() > 0) {
				ultimoIndice = (movList.size() - 1);
				saldo = movList.get(ultimoIndice).getSaldo();
			} else
				saldo = 0f;
		} catch (ParseException exception) {
			exception.printStackTrace();
		}

		return saldo;
	}

	// gera o extrato do usuário
	public void geraExtrato(Date first, Date last) {
		tipoTransaction();// determina se a movimentação é receber ou a pagar
		nameAccountTransaction();// associa nome da conta com a movimentação
		// nameCardTransaction(); //associa nome do cartão com a movimentação
		movList = new ArrayList<Movimentacao>();

		try {
			saldo = 0f;

			// verifica quais são as movimentações desejadas, pela data
			for (int i = 0; i < movListTotal.size(); i++) {
				SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
				Date movDate = dateFormat.parse(movListTotal.get(i)
						.getDataPagamento());

				// Obtém o saldo
				saldo = saldo
						+ (movListTotal.get(i).getCredito() + movListTotal.get(
								i).getDebito());

				movListTotal.get(i).setSaldo(saldo);

				// Verifica se a data está dentro de first e last
				if ((movDate.equals(first) || movDate.after(first))
						&& (movDate.equals(last) || movDate.before(last)))
					movList.add(movListTotal.get(i));
			}

		} catch (NullPointerException nullException) {
			nullException.printStackTrace();
		} catch (ParseException exception) {
			System.err.println("Erro ao formatar a data");
			exception.printStackTrace();
		} finally {
			saldo = 0f;// zera o saldo para outra consulta.
		}
	}

	public <T extends Entidade> Integer updateTables(T entidade,
			String operation) {
		Integer result = 0;
		Dao dao = null;
		if (operation.equalsIgnoreCase("insert")) {
			if (entidade instanceof Grupo) {
				dao = new GrupoDao();
				return result = dao.insert(entidade);
			} else if (entidade instanceof Conta) {
				dao = new ContaDao();
				return result = dao.insert(entidade);
			} else if (entidade instanceof Cartao) {
				dao = new CartaoDao();
				return result = dao.insert(entidade);
			} else if (entidade instanceof Movimentacao) {
				dao = new MovimentacaoDao();
				return result = dao.insert(entidade);
			}
		} else if (operation.equalsIgnoreCase("update")) {
			if (entidade instanceof Grupo) {
				dao = new GrupoDao();
				return result = dao.update(entidade);
			} else if (entidade instanceof Conta) {
				dao = new ContaDao();
				return result = dao.update(entidade);
			} else if (entidade instanceof Cartao) {
				dao = new CartaoDao();
				return result = dao.update(entidade);
			} else if (entidade instanceof Movimentacao) {
				dao = new MovimentacaoDao();
				return result = dao.update(entidade);
			}
		} else if (operation.equalsIgnoreCase("delet")) {// verifica o tipo de
															// releção da
															// entidade a ser
															// deletada com as
															// outras entidades.
			if (entidade instanceof Movimentacao) {
				dao = new MovimentacaoDao();
				return result = dao.delete(entidade);
			} else if (entidade instanceof Grupo) {
				dao = new GrupoDao();
				Grupo grupo = (Grupo) entidade;
				return result = dao.delete(apagaGrupo(grupo, dao));
			} else if (entidade instanceof Conta) {
				dao = new ContaDao();
				Conta conta = (Conta) entidade;
				return result = dao.delete(apagaConta(conta, dao));
			}
		}

		return result;
	}

	// processa o nome da conta da movimentação
	private void nameAccountTransaction() {
		for (int a = 0; a < accountList.size(); a++) {
			for (int b = 0; b < movListTotal.size(); b++) {
				if (accountList.get(a).getIdConta() == movListTotal.get(b)
						.getIdConta())
					movListTotal.get(b).setNomeConta(
							accountList.get(a).getNome());
			}
		}
	}

	// verifica se o tipo da transação é credito ou debito
	private void tipoTransaction() {
		for (int a = 0; a < accountList.size(); a++) {
			for (int b = 0; b < movListTotal.size(); b++) {
				if (movListTotal.get(b).getIdConta() == accountList.get(a)
						.getIdConta()) {
					if (accountList.get(a).getTipo().equals("receber")) {
						movListTotal.get(b).setCredito(
								movListTotal.get(b).getValor());
						movListTotal.get(b).setDebito(0f);
					} else if (accountList.get(a).getTipo().equals("pagar")) {
						movListTotal.get(b).setDebito(
								movListTotal.get(b).getValor() * -1);
						movListTotal.get(b).setCredito(0f);
					}
				}
			}
		}
	}

	private Grupo apagaGrupo(Grupo g, Dao dao) throws RuntimeException {
		Integer result = 0;
		Grupo grupo = g;
		for (int i = 0; i < accountList.size(); i++) {
			if (accountList.get(i).getIdGrupo() == grupo.getIdGrupo()) {
				result = dao.delete(apagaConta(accountList.get(i), dao));
				if (!(result > 0))
					throw new RuntimeException("Erro ao apagar contas");
			} else
				result = 1;
		}

		return grupo;
	}

	// verifica se a conta tem alguma movimentação relacionada se tiver apaga
	private Conta apagaConta(Conta c, Dao dao) throws RuntimeException {
		Integer result = 0;
		Conta conta = c;

		for (int i = 0; i < movListTotal.size(); i++) {
			if (conta.getIdConta() == movListTotal.get(i).getIdConta()) {
				result = dao.delete(movListTotal.get(i));
				if (!(result > 0))
					throw new RuntimeException("Erro ao apagar movimentações");
			}
		}

		return conta;
	}

	// verifica se a aluma movimentação relacionada com o cartão
	// se ouver não apaga se não ouver apaga
	/*private Cartao apagaCartao(Cartao c) throws RuntimeException {
		Cartao card = c;

		for (int i = 0; i < movListTotal.size(); i++) {
			if (card.getIdCard() == movListTotal.get(i).getIdCartao()) {
				throw new RuntimeException("Erro ao apagar cartão");
			}
		}
		return card;
	}

	// processa o nome do cartao da movimentação
	private void nameCardTransaction() {
		for (int a = 0; a < cardList.size(); a++) {
			for (int b = 0; b < movListTotal.size(); b++) {
				if (cardList.get(a).getIdCard() == movListTotal.get(b)
						.getIdCartao())
					movListTotal.get(b).setNomeCartao(
							cardList.get(a).getBandeira());
			}
		}
	}*/

	public Usuario getUsuario() {
		return usuario;
	}

	public List<Movimentacao> getMovList() {
		return movList;
	}

	public Float getSaldo() {
		return saldo;
	}

}
